package com.fingard.dsp.bank.helpers;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.db.JDBCHelper;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.detail.RetAtsBatPayRecDetail;
import com.fingard.dsp.bank.reqrespobj.single.detail.ReqPayRecDetail;
import com.fingard.text.StringHelper;

/**
 * 记录请求的AskNumber，用于当银行不支持记录DSP发的流水号时，根据结果的金额户名账号匹配取回AskNumber；
 * 表字段含流水号、金额、户名、账号、银行的状态
 * 
 * ！！注意：需在finally里显示调用close()方法*/
public class AskNumAmtHelper {
	
	
	private static final int maxTabCount = 5;
	
	public static int getMaxTabCount(){
		return maxTabCount;
	}
	
	private Connection partDbconn = null;
	
	/**！！注意：需在finally里显示调用close()方法
	 * @param 租户
	 * @param 日期*/
	public AskNumAmtHelper(String pTenant, Date pPartDate) throws Exception{
		partDbconn = FGBiz.partTable.getLoaclDbConnByPart(pTenant, pPartDate);
	}
	
	public static String getTableName(String pReqBatchNo){
		int sum = 0;
		for(int i=0;i<pReqBatchNo.length();i++){
			sum += pReqBatchNo.charAt(i);
		}
		return "ASKNUMAMT" + (sum%maxTabCount);
	}
	
	public void close(){
		if(partDbconn != null){
			try{
				partDbconn.close();
			}catch(Exception ex){
				FGBiz.limitMsg.exception("AskNumAmtHelper.closeLocalDbConn", ex);
			}
		}
	}
	
	/**记录请求的AskNumber，写入不成功则抛异常，
	 * ASKNUMBERAMT分成了5个表，
	 * 分别为ASKNUMBERAMT0、ASKNUMBERAMT1、ASKNUMBERAMT2、ASKNUMBERAMT3、ASKNUMBERAMT4
	 * @throws Exception */
	public int saveToLoaclDb(ReqBatPayRec p_reqBat, ReqPayRecDetail pDetail, int pOrderNo) throws Exception{
		String tabName = getTableName(p_reqBat.reqBatchNO);
		String insertSql = "insert into "+tabName+"(REQBATCHNO,ORDERNO,ASKNUMBER,BANKCODE,PAYSENTTIME,OPPACT,OPPACTNAME,AMOUNT,ISBANKRETURNED,CREATEDON,LASTMODIFIEDON,ROWVERSION)values(?,?,?,?,?,?,?,?,?,?,?,?)";
		Object[] objs = new Object[12];
		objs[0] = p_reqBat.reqBatchNO;
		objs[1] = pOrderNo;
		objs[2] = pDetail.askNumber;
		objs[3] = p_reqBat.reqHeader.bankCode;
		objs[4] = new SimpleDateFormat(Format.DateIsoFormatStr).format(p_reqBat.getPayDateTime());
		if("9188".equals(p_reqBat.reqHeader.transType) || "9188-ReSend".equals(p_reqBat.reqHeader.transType)){
			objs[5] = pDetail.payAct;
			objs[6] = pDetail.payName;
		}else if("1988".equals(p_reqBat.reqHeader.transType) || "1988-ReSend".equals(p_reqBat.reqHeader.transType)){
			objs[5] = pDetail.recAct;
			objs[6] = pDetail.recName;
		}
		objs[7] = pDetail.getPayAmount();
		objs[8] = 1;
		objs[9] =  new SimpleDateFormat(Format.DateIsoFormatStr).format(new Date());
		objs[10] = objs[9];
		objs[11] = 1;
		int rowAff = JDBCHelper.update(partDbconn,insertSql,objs);
        if(rowAff != 1){
        	throw new Exception("写入"+tabName+"的影响行数："+rowAff+"，ASKNUMBER："+pDetail.askNumber);
        }
        return rowAff;
	}
	
	private String nowReqBatchNo;
	
	private HashMap<String, Integer> getAskToOrderMap(String pReqBatchNo) throws SQLException{
		String tabName = getTableName(pReqBatchNo);
		String sql = "select ASKNUMBER,ORDERNO from " + tabName + " where REQBATCHNO=?";
		List<Map<String, Object>> listData = JDBCHelper.execQuery(partDbconn, sql, new Object[]{pReqBatchNo});
		HashMap<String, Integer> hash = new HashMap<String, Integer>();
		if(listData != null && listData.size() > 0){
			for(int i=0;i<listData.size();i++){
				Map<String, Object> eachM = listData.get(i);
				String asknumber = eachM.get("ASKNUMBER").toString();
				int orderno = Integer.parseInt(eachM.get("ORDERNO").toString());
				hash.put(asknumber, orderno);
			}
		}
		return hash;
	}
	
	private HashMap<String, Integer> hashAskToOrderMap = null;
	public void initAskMappingOrder(String pReqBatchNo) throws SQLException{
		nowReqBatchNo = pReqBatchNo;
		hashAskToOrderMap = getAskToOrderMap(pReqBatchNo);
	}
	
	/**根据流水号查找序号，映射不到，返回-1*/
	public int mappingOrder(String pAsk){
		if(hashAskToOrderMap.containsKey(pAsk)){
			return hashAskToOrderMap.get(pAsk);
		}
		return -1;
	}
	
	private HashMap<Integer,Map<String, Object>> getAskList(String pReqBatchNo) throws SQLException{
		String tabName = getTableName(pReqBatchNo);
		String sql = "select * from " + tabName + " where REQBATCHNO=?";
		List<Map<String, Object>> listData = JDBCHelper.execQuery(partDbconn, sql, new Object[]{pReqBatchNo});
		HashMap<Integer,Map<String, Object>> hash = new HashMap<Integer,Map<String, Object>>();
		if(listData != null && listData.size() > 0){
			for(int i=0;i<listData.size();i++){
				Map<String, Object> eachM = listData.get(i);
				int orderno = Integer.parseInt(eachM.get("ORDERNO").toString());
				hash.put(orderno, eachM);
			}
		}
		return hash;
	}
	
	private HashMap<Integer,Map<String, Object>> hashOrderToAskData = null;
	/**初始化匹配，根据序号匹配流水号*/
	public void initMatch(String pReqBatchNo) throws SQLException{
		nowReqBatchNo = pReqBatchNo;
		hashOrderToAskData = getAskList(pReqBatchNo);
	}
	
	/**校验总笔数，用于全部匹配完之后，校验总数是否一致*/
	public HelperResp checkMatchCount(int pRdCount, int pMatchCount){
		HelperResp resp = new HelperResp();
		if(hashOrderToAskData.size() == pRdCount && hashOrderToAskData.size() == pMatchCount){
			resp.isCompleted = true;
		}else{
			resp.isCompleted = false;
			resp.sbMsg.append("总数校验不通过，数据库记录数："+hashOrderToAskData.size()+"，查询结果记录数："+pRdCount+"，匹配成功数："+pMatchCount);
		}
		return resp;
	}
	/**匹配账号时，如果银行返回的已有位数都相同，也认为匹配成功，针对邮储响应的对方账号少了一位的情况*/
	public boolean matchActByStartWith = false;
	
	/**根据账号户名金额序号匹配AskNumber，匹配成功则赋值pDetail.postScript
	 * @throws Exception */
	public boolean matchAskNum(String pTransType, RetAtsBatPayRecDetail pDetail, int pOrderNo, boolean pIsFinalState) throws Exception{
		if(hashOrderToAskData.containsKey(pOrderNo)){
			Map<String, Object> eachM = hashOrderToAskData.get(pOrderNo);
			/**"OPPACT VARCHAR(128)," +
    					"OPPACTNAME VARCHAR(256)," +
    					"AMOUNT DECIMAL(18,2)," +
    					"ORDERNO INTEGER NOT NULL," +//排序字段
    					"RESULT VARCHAR(64)," +//状态
    					"MEMO VARCHAR(256)," +//Memo
    					"PAYINFOCODE VARCHAR(64)," +//PayInfoCode*/
			String dbOPPACT = eachM.get("OPPACT")!=null?eachM.get("OPPACT").toString():"";
			String dbOPPACTNAME = eachM.get("OPPACTNAME")!=null?eachM.get("OPPACTNAME").toString():"";
			BigDecimal dbAMOUNT = new BigDecimal(eachM.get("AMOUNT").toString());
			
			String chkOPPACT = null;
			String chkOPPACTNAME = null;
			BigDecimal chkAMOUNT = new BigDecimal(pDetail.payAmount);
			if("9198".equals(pTransType)){
				chkOPPACT = pDetail.payAct;
				chkOPPACTNAME = pDetail.payName;
			}else if("1998".equals(pTransType)){
				chkOPPACT = pDetail.recAct;
				chkOPPACTNAME = pDetail.recName;
			}
			//String cmpStrDbAMOUNT = Format.DecimalAmtFormat.format(dbAMOUNT);
			//String cmpStrChkAMOUNT = Format.DecimalAmtFormat.format(chkAMOUNT);
			boolean isChkedOppAct = false;//对方账号是否校验通过
			if(dbOPPACT.equals(chkOPPACT)){
				isChkedOppAct = true;
			}else if(matchActByStartWith){
				isChkedOppAct = dbOPPACT.startsWith(chkOPPACT);
			}
			if(isChkedOppAct && dbOPPACTNAME.equals(chkOPPACTNAME) && dbAMOUNT.compareTo(chkAMOUNT) == 0){
				String dbRESULT = eachM.get("RESULT")!=null?eachM.get("RESULT").toString():"";
				String dbMEMO = eachM.get("MEMO")!=null?eachM.get("MEMO").toString():"";
				String dbPAYINFOCODE = eachM.get("PAYINFOCODE")!=null?eachM.get("PAYINFOCODE").toString():"";
				
				String chkRESULT = StringHelper.subStringByByte(pDetail.result, "utf-8", 64);
				String chkMEMO = StringHelper.subStringByByte(pDetail.memo, "utf-8", 256);
				String chkPAYINFOCODE = StringHelper.subStringByByte(pDetail.payInfoCode, "utf-8", 128);
				
				int dbISBANKRETURNED = Integer.parseInt(eachM.get("ISBANKRETURNED").toString());
				int dbROWVERSION = Integer.parseInt(eachM.get("ROWVERSION").toString());
				
				if(dbISBANKRETURNED == 1 && dbRESULT.length() == 0 && dbMEMO.length() == 0 && dbPAYINFOCODE.length() == 0){
					if(pIsFinalState){
						String tabName = getTableName(nowReqBatchNo);
						String updSql = "update " + tabName + " set RESULT=?,MEMO=?,PAYINFOCODE=?,ISBANKRETURNED=2,ROWVERSION=ROWVERSION+1,LASTMODIFIEDON=? where REQBATCHNO=? and ASKNUMBER=? and OPPACT=? and OPPACTNAME=? and AMOUNT=? and ORDERNO=? and ROWVERSION=? and ISBANKRETURNED=1";
						Object[] objs = new Object[11];
						objs[0] = chkRESULT;
						objs[1] = chkMEMO;
						objs[2] = chkPAYINFOCODE;
						objs[3] =  new SimpleDateFormat(Format.DateIsoFormatStr).format(new Date());
						objs[4] = nowReqBatchNo;
						objs[5] = eachM.get("ASKNUMBER").toString();
						objs[6] = dbOPPACT;
						objs[7] = dbOPPACTNAME;
						objs[8] = dbAMOUNT;
						objs[9] = pOrderNo;
						objs[10] = dbROWVERSION;
						
						int rowAff = JDBCHelper.update(partDbconn,updSql,objs);
				        if(rowAff != 1){
				        	throw new Exception("更新"+tabName+"的影响行数："+rowAff+"，ASKNUMBER："+eachM.get("ASKNUMBER").toString());
				        }else{
				        	pDetail.postScript = eachM.get("ASKNUMBER").toString();
							return true;
				        }
					}else{//非终态，先不更新结果
						pDetail.postScript = eachM.get("ASKNUMBER").toString();
						return true;
					}
				}else if(dbISBANKRETURNED == 2 && dbRESULT.equals(chkRESULT) && dbMEMO.equals(chkMEMO) && dbPAYINFOCODE.equals(chkPAYINFOCODE)){
					pDetail.postScript = eachM.get("ASKNUMBER").toString();
					return true;
				}else{
					throw new Exception("第"+pOrderNo+"笔提交的顺序与响应的顺序不一致，结果校验不通过，数据库中(RESULT,MEMO,PAYINFOCODE)值分别为("+dbRESULT+","+dbMEMO+","+dbPAYINFOCODE+")，响应值为("+chkRESULT+","+chkMEMO+","+chkPAYINFOCODE+")");
				}
			}else{
				throw new Exception("第"+pOrderNo+"笔提交的顺序与响应的顺序不一致，结果校验不通过，数据库中(OPPACT,OPPACTNAME,AMOUNT)值分别为("+dbOPPACT+","+dbOPPACTNAME+","+dbAMOUNT+")，响应值为("+chkOPPACT+","+chkOPPACTNAME+","+chkAMOUNT+")");
			}
			
		}else{
			throw new Exception("第"+pOrderNo+"笔未能匹配到ASKNUMBERAMT记录");
		}
	}
}
